package org.jsbd.boss.service.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.jsbd.boss.common.DataGridModel;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.dao.IBookDao;
import org.jsbd.boss.dao.IBookGroupDao;
import org.jsbd.boss.dao.IBookMarkFailCountDao;
import org.jsbd.boss.domian.Book;
import org.jsbd.boss.domian.BookMarkFailCount;
import org.jsbd.boss.service.IBookService;
import org.jsbd.boss.util.CacheKey;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

@Service("bookService")
public class BookServiceImpl implements IBookService {

	@Autowired
	private IBookDao bookDao;
	@Autowired
	private IBookGroupDao bookGroupDao;
	@Autowired
	private IBookMarkFailCountDao bookMarkFailCountDao;

	@Resource
	private RedisClient<String, String> redisClient;

	private static final long EXPIRE_TIME = 10;

	private static final Integer ONE = Integer.valueOf(1);
	private static final BigDecimal ZERO = new BigDecimal(0);

	@Override
	public void save(Book book) {
		book.setPayMoney(ZERO);
		bookDao.save(book);
	}

	@Override
	public void save(List<Book> list) {

		for (Book book : list) {
			book.setPayMoney(ZERO);
		}
		bookDao.save(list);
	}

	@Override
	@Transactional("transactionManagerCrack")
	public long saveToTemp(List<Book> list) {

		if (redisClient.evalSetNx(CacheKey.BOOK_EXCEL_IMPORT_LOCK, EXPIRE_TIME)) {
			// 先清空临时表，然后存入
			bookDao.clearTemp();
			bookDao.saveToTemp(list);

			redisClient.remove(CacheKey.BOOK_EXCEL_IMPORT_LOCK);
		}

		long counter = redisClient.getValAndAdd(CacheKey.BOOK_EXCEL_IMPORT_COUNT, 1);
		return counter;
	}

	@Override
	@Transactional("transactionManagerCrack")
	public void tempToBook(long counter, int bookGroupId) throws Exception {

		if (redisClient.getVal(CacheKey.BOOK_EXCEL_IMPORT_COUNT) == counter) {
			if (redisClient.evalSetNx(CacheKey.BOOK_EXCEL_IMPORT_LOCK, EXPIRE_TIME)) {
				List<Book> list = bookDao.getTempList();
				List<Book> books = bookDao.getGroupList(bookGroupId);

				boolean has = false;
				boolean modified = false;
				for (Book book : list) {
					book.setBookGroupId(bookGroupId);
					has = false;
					for (Book bk : books) {
						if (bk.getFlag().intValue() == 0 && bk.equals(book)) {
							book.setId(bk.getId());
							// 找到做更新操作
							bookDao.updateTotalMoney(book);
							modified = true;
							bk.setFlag(ONE);
							has = true;
							break;
						}
					}
					if (has) {
						book.setFlag(ONE);
					} else {
						// 没找到 做插入操作
						book.setPayMoney(ZERO);
						bookDao.save(book);
						book.setFlag(ONE);
						modified = true;
					}
				}
				// 删除 数据库中 多余书籍
				List<Integer> ids = new LinkedList<>();
				for (Book book : books) {
					// 未找到
					if (book.getFlag().intValue() == 0) {
						ids.add(book.getId());
					}
				}
				// 未找到，做清除操作
				if (ids.size() > 0) {
					bookDao.delete(ids);
					modified = true;
				}
				if (modified) {
					bookGroupDao.updateModifyTime(bookGroupId);
				}
				redisClient.remove(CacheKey.BOOK_EXCEL_IMPORT_LOCK);
			}
		} else {
			throw new Exception("临时表数据已被修改！");
		}
	}

	@Override
	public void update(Book book) {
		bookDao.update(book);
	}

	@Override
	public Book get(Book book) {
		return bookDao.get(book);
	}

	@Override
	public Book getByMark(String mark) throws Exception {
		Assert.notNull(mark, "mark不能为空");
		Book book = bookDao.getByMark(mark);
		if (book != null) {
			book.updateChapter();
			return book;
		}
		return null;
	}

	@Override
	public Book getById(Integer id) {
		return bookDao.getById(id);
	}

	@Override
	public List<Book> getList(Book book) {
		return bookDao.getList(book);
	}

	@Override
	public Map<String, Object> getListPage(DataGridModel page, Book book) {

		book = (book == null ? new Book() : book);
		book.setPageInfo(page);
		Map<String, Object> results = new HashMap<String, Object>();
		results.put("total", bookDao.getListPageCount(book));

		List<Book> list = (List<Book>) bookDao.getList(book);

		results.put("rows", list);
		return results;
	}

	@Override
	public Map<String, Object> getTempPage(DataGridModel page, Book book) {

		book = (book == null ? new Book() : book);
		book.setPageInfo(page);
		Map<String, Object> results = new HashMap<String, Object>();
		results.put("total", bookDao.getTempListPageCount(book));

		@SuppressWarnings("unchecked")
		List<Book> list = (List<Book>) bookDao.getTempListByPage(book);

		// for (Book bk : list) {
		// Integer count = bookDao.getTempCountByMarkAndName(bk);
		// // 标记 1新增 2修改 3有重复数据
		// bk.setTag(count == 1 ? 2 : (count == 0 ? 1 : 3));
		// }

		results.put("rows", list);
		return results;
	}

	@Override
	public void delete(List<Integer> ids) {
		bookDao.delete(ids);
	}

	@Override
	@Transactional("transactionManagerCrack")
	public int revertAllBookPayMoney() {
		List<Book> list = bookDao.getRevertBookList();
		for (Book book : list) {
			bookDao.saveBookRevertLog(book);
			bookDao.revertBookPayMoney(book.getId());
		}
		//set failCount=0
		bookMarkFailCountDao.resetAllMarkFailCount();
		
		return list.size();
	}

	@Override
	public void updateFailCount(Integer bookId, String mark) {

		Assert.notNull(bookId, "书籍编号不能为空");
		Assert.notNull(mark, "mark不能为空");

		if (redisClient.evalSetNx(CacheKey.BOOK_MARK_FAIL_COUNT_LOCK, 2)) {
			bookDao.updateFailCount(bookId);
			BookMarkFailCount query = new BookMarkFailCount();
			query.setBookId(bookId);
			query.setMark(mark);
			BookMarkFailCount bookMarkFailCount = bookMarkFailCountDao.get(query);
			if (bookMarkFailCount == null) {
				query.setFailCount(1);
				bookMarkFailCountDao.save(query);
			} else {
				bookMarkFailCountDao.updateFailCount(query);
			}
			redisClient.remove(CacheKey.BOOK_MARK_FAIL_COUNT_LOCK);
		}
	}
}
